from stages import Shagstage, GlobalStage, Rip
from util import mypopen, ShaggerVersion
from subprocess import PIPE
from config import Config

import os
from mutagen.flac import FLAC

class FlacEncode(Shagstage):
    
    previous = Rip.suffix
    working = "encoding.flac"
    suffix = "cdda.flac"
    
    def __init__(self, shagger, track):
        Shagstage.__init__(self, shagger, track)    
    
    def preamble(self):
        return "Flac Encoder"
    
    def canWork(self):
        files = self.fetchFiles()
        for file in files:
            if file.endswith(self.previous):
                return True            
                    
    def work(self):
        if not self.canWork():
            return False
        
        self.log ("Encoding track:")
        flaccommand = ['flac']
                
        previousfile = self.filename( self.previous )
        workingfile = self.filename( self.working )

        args =  [ "-o", workingfile, "-s", "-f", previousfile ] #-q for quiet?
        proc = mypopen(flaccommand + args) #.communicate()[0]
        (pid, out) = os.waitpid( proc.pid, 0 )
        
        #print >> sys.stderr, "Child returned", (pid, out)
        
        if (out == 0):
            
            outfile = self.filename(self.suffix)
            
            self.log("Renaming %s to %s" % (workingfile, outfile))
            os.rename(workingfile, outfile)
            os.remove(previousfile)
            self.log("Encoded track to %s:" % outfile )
            return True    
        else:
            raise ProblemProcessingException, "encoding error %d" % out


class FlacTag(Shagstage):
    
    previous = FlacEncode.suffix    
    suffix = "tagged.flac"
    #suffix = FinalDestination.previous
    
    def __init__(self, shagger, track):
        Shagstage.__init__(self, shagger, track)    
    
    def preamble(self):
        return "Flac Tagger"     
    
    def canWork(self):
        files = self.fetchFiles()
        for file in files:
            if file.endswith(self.previous):
                return True     
                    
    def work(self):
        if not self.canWork():
            return False
        
        previousfile = self.filename( self.previous )
        audio = FLAC( previousfile )        
        
        track = self.shagger.musicBrain.getTracks()[self.track]
        
        struct = {}
        
        struct['MUSICBRAINZ_ARTISID'] = track.getArtistId()    
        struct['ARTIST'] = track.getArtist()
        struct['TITLE'] = track.getTitle()  
        #struct['TRACKNUMBER'] = track.getTrackNumber()
        struct['MUSICBRAINZ_TRACKID'] = track.getTrackId()
        struct['MUSICBRAINZ_ARTISID'] = track.getArtistId()
        struct['ARTIST'] = track.getArtist()
        struct['TITLE'] = track.getTitle()        
        struct['MUSICBRAINZ_TRACKID'] = track.getTrackId()
        
        data = track.getAlbum()
        struct['ALBUM'] = data.getAlbumName()
        #struct['TOTALTRACKS'] = data.getTotalTracks()
        
        struct['MUSICBRAINZ_DISCID'] = data.getDiscId()        
        struct['ALBUMARTIST']=data.getAlbumArtist()
        struct['ALBUMARTISTSORT']=data.getAlbumArtistSort()
        struct['MUSICBRAINZ_ALBUMID'] = data.getAlbumId()
        struct['RELEASESTATUS'] = data.getReleaseStatus()
        struct['RELEASETYPE'] = data.getReleaseType()
        struct['MUSICBRAINZ_ALBUMARTISTID'] = data.getAlbumArtistId()
        
        #struct['COMPILATION'] = data.getCompilation()
        
        struct['TAGINFO'] = "Shagger v%f" % ShaggerVersion()
        
        #For no obvious reason, these give more grief than the others:
        #something to fo with numeric types?
        print( "Tagging track %r / %r (compilation: %r)" % (track.getTrackNumber(), data.getTotalTracks(), data.getCompilation()  ))
        struct['TRACKNUMBER'] = track.getTrackNumber()
        struct['TOTALTRACKS'] = data.getTotalTracks()
        struct['COMPILATION'] = data.getCompilation()
        #must make this more elegant!
        struct['DATE'] = data.getDate()
        struct['ASIN']=data.getAsin()
        struct['DISCOGS']=data.getDiscogs()
        
        for tag in struct:
            if struct[tag] != None:
                audio[tag] = struct[tag]

        print audio.pprint()
        x = audio.save()
        print "Tag saved (%r)" % x
        
        
        outfile = self.filename(self.suffix)
           
        self.log("Renaming %s to %s" % (previousfile, outfile))
        os.rename(previousfile, outfile)
        self.log("Tagged track %s:" % outfile )
        return True
 
class AddFlacReplayGain(GlobalStage):
    
    def __init__(self, shagger):
        GlobalStage.__init__(self, shagger) 
    
    def preamble(self):
        return "Add Flac Replay Gain"
    
    def canWork(self):
        files = self.shagger.fileSubset("flac")
        
        if( len(files) == 0):
            return False
        
        audio = FLAC( files[0] )
        if( audio.has_key("REPLAYGAIN_ALBUM_GAIN") ):
            return False        
        
        return True

    def work(self):
        
        command = ["metaflac"]
        files = self.shagger.fileSubset("flac")
                            
        args =  [ "--add-replay-gain" ] + files #-q for quiet?
        #print "Adding replay gain... %r %r" % (command, args)
        
        proc = mypopen(command + args) #.communicate()[0]
        (pid, out) = os.waitpid( proc.pid, 0 )
        
        #print >> sys.stderr, "Child returned", (pid, out)
        
        if (out != 0):
            raise ProblemProcessingException, "problem adding gain %d" % out
        else:
            return True    

class ShnSplit(GlobalStage):
    cuefile = "";
    flacfile = "";
    
    def __init__( self, shagger ):
        GlobalStage.__init__(self, shagger) 
        
    def preamble(self):
        return "Splitting up Flac / Ape"
    
    def canWork( self ):
        #first locate a .cue file
        cues = self.shagger.fileSubset( "cue" )        
        if( len( cues ) != 1 ):            
            return False
        
        self.cuefile = cues[0]
        
        #now locate exactly 1 .flac or .ape
        flacs = self.shagger.fileSubset("flac")
        if( len( flacs ) == 1):
            self.flacfile = flacs[0]
            return True
        
        apes = self.shagger.fileSubset( "ape" )
        if( len( apes ) == 1):
            self.flacfile = apes[0]
            return True
        
        return False
    
    def work( self ):
        
        #From the manual: http://www.python.org/doc/2.5.2/lib/node535.html
        #output=`dmesg | grep hda`
        #==>
        #p1 = Popen(["dmesg"], stdout=PIPE)
        #p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
        #output = p2.communicate()[0]        
        
        cuebreakpoints = ['cuebreakpoints']
        args =  [ self.cuefile ] 
        
        proc1 = mypopen(cuebreakpoints + args, stdout=PIPE) 
        (pid, out) = os.waitpid( proc1.pid, 0 )
        
        #print >> sys.stderr, "Child returned", (pid, out)        
        if (out != 0):  
            self.shagger.log( "Problem running cuebreakpoints" )
            return False
        
        shnsplit = ['shnsplit']
        args =  [ "-o", "flac", "-d", self.shagger.dir(), self.flacfile] 
        
        proc2 = mypopen(shnsplit + args, stdin=proc1.stdout) 
        (pid, out) = os.waitpid( proc2.pid, 0 )
        
        if (out != 0):  
            self.shagger.log( "Problem running cuebreakpoints" )
            return False
        
        self.shagger.log( "File split succesfully!" )
        #possibly a bit scary... but we'll have the wrong # of flacflies if we don't do this
        if( Config[ "ultracautious" ] == False):
            os.remove( self.flacfile )
        return True
    
    
       
        
        
        
    
